home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / quicktime / quicktimeintro / play movie w.controller / common files / winframework.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-06  |  28.4 KB  |  966 lines

  1. //////////
  2. //
  3. //    File:        WinFramework.c
  4. //
  5. //    Contains:    Code for the QuickTime sample code framework that is specific to Windows. 
  6. //                This code handles windows, menus, events, and other low-level things. Put your
  7. //                application-specific code into the file ComApplication.c. 
  8. //
  9. //    Written by:    Tim Monroe
  10. //                Based on the QTShell code written by Tim Monroe, which in turn was based on the MDIPlayer
  11. //                code written by Brian S. Friedkin (Aug 5, 1996). This current version is now very far removed from
  12. //                MDIPlayer.
  13. //
  14. //    Copyright:    © 1999 by Apple Computer, Inc., all rights reserved.
  15. //
  16. //    Change History (most recent first):
  17. //
  18. //       <6>         01/14/00    rtm        reworked window-drawing code (WM_PAINT message) to support graphics files
  19. //       <5>         01/05/00    rtm        minor tweaks to QuickTime initialization in WinMain
  20. //       <4>         12/26/99    rtm        added WM_LBUTTONDOWN processing to QTFrame_MovieWndProc; minor reorganization
  21. //                                    of QTFrame_MovieWndProc so that myMacEvent and myIsHandled are in scope for
  22. //                                    that message
  23. //       <3>         12/16/99    rtm        made minor change to QTFrame_MovieWndProc so that QTApp_HandleEvent is called
  24. //                                    even if the window has no movie controller
  25. //       <2>         11/29/99    rtm        modified "Save changes" dialog box to use Macintosh wordings prompted by move
  26. //                                    to Navigation Services
  27. //       <1>         11/05/99    rtm        first file; based on earlier sample code
  28. //       
  29. //////////
  30.  
  31. //////////
  32. //
  33. // header files
  34. //
  35. //////////
  36.  
  37. #include "WinFramework.h"
  38.  
  39.  
  40. //////////
  41. //
  42. // global variables
  43. //
  44. //////////
  45.  
  46. BOOL                gShuttingDown = false;                // are we shutting down?
  47. BOOL                gWeAreSizingWindow = false;            // are we resizing a window?
  48. BOOL                gWeAreCreatingWindow = false;        // are we creating a window?
  49.  
  50. HANDLE                ghInst;                                // the instance of this application
  51. HWND                ghWnd;                                // the MDI frame window; this window has the menu bar
  52. HWND                ghWndMDIClient;                     // the MDI client window
  53.  
  54. char                gChildName[] = "QTShellChild";
  55. char                gMovieType[] = "QuickTime Movie";
  56.  
  57. short                 gAppResFile = kInvalidFileRefNum;    // file reference number for this application's resource file
  58. FSSpec                gAppFSSpec;                            // file specification for the application itself
  59. char                gAppName[20];                        // the name of this application
  60.  
  61. LPSTR                gCmdLine;                            // the command line passed to WinMain
  62.  
  63. extern Rect            gMCResizeBounds;                    // maximum size for any movie window
  64.  
  65.  
  66. //////////
  67. //
  68. // WinMain
  69. // The main function for this application.
  70. //
  71. // Set up the application's execution environment; make sure QuickTime (etc.) is installed,
  72. // then start handling events. If we terminate before reaching the message loop, we should
  73. // return 0.
  74. //
  75. //////////
  76.  
  77. int CALLBACK WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR theCmdLine, int nCmdShow)
  78. {
  79.     HANDLE                myAccel;
  80.     HWND                myWindowFrame;
  81.     MSG                    myMsg;
  82.     WNDCLASSEX            myWC;
  83.     char                myFileName[MAX_PATH];
  84.     DWORD                myLength;
  85.     OSErr                myErr = noErr;
  86.  
  87.     ghInst = hInstance;
  88.     gCmdLine = theCmdLine;
  89.     
  90.     if (hPrevInstance == NULL) {
  91.         LoadString(hInstance, IDS_APPNAME, gAppName, sizeof(gAppName));
  92.         
  93.         // register the frame window class
  94.         myWC.cbSize        = sizeof(WNDCLASSEX);
  95.         myWC.style         = CS_HREDRAW | CS_VREDRAW;
  96.         myWC.lpfnWndProc   = (WNDPROC)QTFrame_FrameWndProc;
  97.         myWC.cbClsExtra    = 0;
  98.         myWC.cbWndExtra    = 0;
  99.         myWC.hInstance     = hInstance;
  100.         myWC.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON));
  101.         myWC.hCursor       = LoadCursor(NULL, IDC_ARROW);
  102.         myWC.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  103.         myWC.lpszMenuName  = gAppName;
  104.         myWC.lpszClassName = gAppName;
  105.         myWC.hIconSm       = LoadImage(hInstance, MAKEINTRESOURCE(IDI_APPICON), IMAGE_ICON, 16, 16, 0);
  106.                                      
  107.         if (!RegisterClassEx(&myWC)) {
  108.             if (!RegisterClass((LPWNDCLASS)&myWC.style))
  109.                 return(0);
  110.         }
  111.  
  112.         // register the movie child window class
  113.         myWC.cbSize        = sizeof(WNDCLASSEX);
  114.         myWC.style         = 0;
  115.         myWC.lpfnWndProc   = (WNDPROC)QTFrame_MovieWndProc;
  116.         myWC.cbClsExtra    = 0;
  117.         myWC.cbWndExtra    = 0;
  118.         myWC.hInstance     = hInstance;
  119.         myWC.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CHILDICON));
  120.         // to avoid having QuickTime VR "fight" with the system over the cursor,
  121.         // we set the client area cursor to NULL; this means that for QuickTime
  122.         // movies, we'll need to change the cursor to an arrow manually; see the
  123.         // handling of the WM_MOUSEMOVE message in QTFrame_MovieWndProc
  124.         myWC.hCursor       = NULL;
  125.         myWC.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  126.         myWC.lpszMenuName  = NULL;
  127.         myWC.lpszClassName = gChildName;
  128.         myWC.hIconSm       = LoadImage(hInstance, MAKEINTRESOURCE(IDI_CHILDICON), IMAGE_ICON, 16, 16, 0);
  129.                                      
  130.         if (!RegisterClassEx(&myWC)) {
  131.             if (!RegisterClass((LPWNDCLASS)&myWC.style))
  132.                 return(0);
  133.         }
  134.     }
  135.  
  136.     // load accelerators
  137.     myAccel = LoadAccelerators(hInstance, gAppName);
  138.  
  139.     // initialize QuickTime Media Layer and QuickTime; alert the user and return 0 if unsuccessful
  140.     myErr = InitializeQTML(0L);
  141.     if (myErr != noErr) {
  142.         MessageBox(NULL, "QuickTime is not installed on this computer. Exiting.", gAppName, MB_OK | MB_APPLMODAL);
  143.         return(0);
  144.     }
  145.     
  146.     myErr = EnterMovies();
  147.     if (myErr != noErr) {
  148.         MessageBox(NULL, "Could not initialize QuickTime. Exiting.", gAppName, MB_OK | MB_APPLMODAL);
  149.         return(0);
  150.     }
  151.  
  152.     // get the application's resource file, if it exists
  153.     myLength = GetModuleFileName(NULL, myFileName, MAX_PATH);        // NULL means: the current process
  154.     if (myLength != 0) {
  155.         NativePathNameToFSSpec(myFileName, &gAppFSSpec, kFullNativePath);
  156.  
  157.         gAppResFile = FSpOpenResFile(&gAppFSSpec, fsRdWrPerm);
  158.         if (gAppResFile != kInvalidFileRefNum)
  159.             UseResFile(gAppResFile);
  160.     }
  161.  
  162.     // do any application-specific initialization that must occur before the frame window is created
  163.     QTApp_Init(kInitAppPhase_BeforeCreateFrameWindow);
  164.     
  165.     // create the main frame window
  166.     myWindowFrame = CreateWindow(gAppName, gAppName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  167.                                        CW_USEDEFAULT, 
  168.                                        CW_USEDEFAULT,
  169.                                      CW_USEDEFAULT, 
  170.                                      CW_USEDEFAULT,
  171.                                      NULL, 
  172.                                      NULL, 
  173.                                      hInstance, 
  174.                                      NULL);
  175.     ghWnd = myWindowFrame;
  176.     
  177.     // make sure we got a frame window
  178.     if (myWindowFrame == NULL)
  179.         return(0);
  180.         
  181.     // show the window
  182.     ShowWindow(myWindowFrame, nCmdShow);
  183.     UpdateWindow(myWindowFrame);
  184.     
  185.     // do any application-specific initialization that must occur after the frame window is created
  186.     QTApp_Init(kInitAppPhase_AfterCreateFrameWindow);
  187.     
  188.     // get and process events until the user quits
  189.     while (GetMessage(&myMsg, NULL, 0, 0)) {    
  190.         if (!TranslateMDISysAccel(ghWndMDIClient, &myMsg)) {
  191.             if (!TranslateAccelerator(myWindowFrame, myAccel, &myMsg)) {
  192.                 TranslateMessage(&myMsg);
  193.                 DispatchMessage(&myMsg);
  194.             }
  195.         }
  196.     }
  197.  
  198.     // close the application's resource file, if it was previously opened
  199.     if (gAppResFile != kInvalidFileRefNum)
  200.         CloseResFile(gAppResFile);
  201.  
  202.     // terminate the QuickTime Media Layer
  203.     ExitMovies();
  204.     TerminateQTML();
  205.  
  206.     return(myMsg.wParam);            // returns the value from PostQuitMessage
  207. }
  208.  
  209.  
  210. //////////
  211. //
  212. // QTFrame_FrameWndProc
  213. // The window procedure for the MDI frame window.
  214. //
  215. //////////
  216.  
  217. LRESULT CALLBACK QTFrame_FrameWndProc (HWND theWnd, UINT theMessage, UINT wParam, LONG lParam)
  218. {
  219.     HWND                   myChild;
  220.  
  221.     switch (theMessage) {
  222.     
  223.         case WM_CREATE: {
  224.             CLIENTCREATESTRUCT        myClientStruct = {0};
  225.  
  226.             myClientStruct.hWindowMenu  = GetSubMenu(GetMenu(theWnd), WINDOWMENU);
  227.             myClientStruct.idFirstChild = IDM_WINDOWCHILD;
  228.             
  229.             // create the MDI client filling the client area
  230.             ghWndMDIClient = CreateWindow("mdiclient",
  231.                                          NULL,
  232.                                          WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,
  233.                                          0, 0, 0, 0,
  234.                                          theWnd,
  235.                                          (HMENU)0xCAC,
  236.                                          ghInst,
  237.                                          (LPVOID)&myClientStruct);
  238.             
  239.             // set initial menu state
  240.             QTFrame_AdjustMenus(NULL, GetMenu(theWnd));
  241.             
  242.             if (ghWndMDIClient != NULL)
  243.                 ShowWindow(ghWndMDIClient, SW_SHOW);
  244.             
  245.             return(0);
  246.         }
  247.  
  248.         case WM_ACTIVATE:
  249.             // the MDI frame window is being activated or deactivated;
  250.             // activate or deactivate any active child window by sending this message to DefMDIChildProc 
  251.             myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  252.             if (IsWindow(myChild))
  253.                 SendMessage(myChild, WM_ACTIVATE, wParam, lParam);
  254.             break;
  255.  
  256.         case WM_COMMAND: {
  257.  
  258.             switch (LOWORD(wParam)) {
  259.                 case IDM_FILENEW:
  260.                 case IDM_FILEOPEN:
  261.                 case IDM_FILECLOSE:
  262.                 case IDM_EXIT:
  263.                     QTFrame_HandleFileMenuItem(NULL, LOWORD(wParam));
  264.                     return(0);
  265.  
  266.                 case IDM_FILESAVE:
  267.                 case IDM_FILESAVEAS:
  268.                     // save the active child window
  269.                     myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  270.                     if (IsWindow(myChild))
  271.                         SendMessage(myChild, WM_COMMAND, wParam, lParam);
  272.                     return(0);
  273.  
  274.                 case IDM_WINDOWTILE:
  275.                     SendMessage(ghWndMDIClient, WM_MDITILE, 0, 0L);
  276.                     return(0);
  277.  
  278.                 case IDM_WINDOWCASCADE:
  279.                     SendMessage(ghWndMDIClient, WM_MDICASCADE, 0, 0L);
  280.                     return(0);
  281.  
  282.                 case IDM_WINDOWICONS:
  283.                     SendMessage(ghWndMDIClient, WM_MDIICONARRANGE, 0, 0L);
  284.                     return(0);
  285.  
  286.                 case IDM_WINDOWCLOSEALL: {
  287.                     WindowReference        myWindow, myNextWindow;
  288.             
  289.                     // walk the window list and destroy any open windows
  290.                     myWindow = QTFrame_GetFrontMovieWindow();
  291.                     while (myWindow != NULL) {
  292.                         myNextWindow = QTFrame_GetNextMovieWindow(myWindow);
  293.                         SendMessage(myWindow, WM_CLOSE, 0L, 0L);
  294.                         myWindow = myNextWindow;
  295.                     }
  296.                     
  297.                     return(0);
  298.                 }
  299.  
  300.                 case IDM_ABOUT:
  301.                     QTFrame_ShowAboutBox();
  302.                     return(0);
  303.  
  304.                 default:                
  305.                     // pass this message to the active child window...
  306.                     myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  307.                     if (IsWindow(myChild))
  308.                         SendMessage(myChild, WM_COMMAND, wParam, lParam);
  309.  
  310.                     // ...then do any application-specific menu handling, if no movie windows are open...
  311.                     if (myChild == NULL)
  312.                         QTApp_HandleMenu((UInt16)LOWORD(wParam));
  313.                     
  314.                     // ...and then pass it to DefFrameProc
  315.                     break;
  316.             }
  317.             break;
  318.         }
  319.  
  320.         case WM_OPENDROPPEDFILES:
  321.             // open any movie files that were dropped onto the application icon
  322.             QTFrame_OpenCommandLineMovies(gCmdLine);
  323.             return(0);
  324.  
  325.         case WM_INITMENU:
  326.             if (GetMenu(theWnd) == (HMENU)wParam)
  327.                 return(QTFrame_AdjustMenus((HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L), (HMENU)wParam));
  328.             return(1);
  329.  
  330.         case WM_CLOSE:
  331.             // if we're not already in the process of shutting down,
  332.             // simulate the selection of the Quit menu command
  333.             if (!gShuttingDown) {
  334.                 SendMessage(ghWnd, WM_COMMAND, IDM_EXIT, 0L);
  335.                 return(0);
  336.             }
  337.             break;
  338.             
  339.         case WM_DESTROY:
  340.             // do any application-specific shutdown
  341.             QTApp_Stop(kStopAppPhase_AfterDestroyWindows);
  342.             PostQuitMessage(0);
  343.             break;
  344.     }
  345.     
  346.     return(DefFrameProc(theWnd, ghWndMDIClient, theMessage, wParam, lParam));
  347. }
  348.  
  349.  
  350. //////////
  351. //
  352. // QTFrame_MovieWndProc
  353. // The window procedure for a movie window.
  354. //
  355. //////////
  356.  
  357. LRESULT CALLBACK QTFrame_MovieWndProc (HWND theWnd, UINT theMessage, UINT wParam, LONG lParam)
  358. {
  359.     WPARAM                myWidth, myHeight;
  360.     MovieController        myMC = NULL;
  361.     Movie                myMovie = NULL;
  362.     WindowObject        myWindowObject = NULL;
  363.     MSG                    myMsg = {0};
  364.     EventRecord            myMacEvent;
  365.     Boolean                myIsHandled = false;
  366.  
  367.     // get the window object, movie, and movie controller for this window
  368.     myWindowObject = QTFrame_GetWindowObjectFromWindow(theWnd);
  369.     if (myWindowObject != NULL) {
  370.         myMC = (**myWindowObject).fController;
  371.         myMovie = (**myWindowObject).fMovie;
  372.     }
  373.  
  374.     // give the movie controller this message first
  375.     if (!gShuttingDown) {
  376.         LONG            myPoints = GetMessagePos();
  377.  
  378.         myMsg.hwnd = theWnd;
  379.         myMsg.message = theMessage;
  380.         myMsg.wParam = wParam;
  381.         myMsg.lParam = lParam;
  382.         myMsg.time = GetMessageTime();
  383.         myMsg.pt.x = LOWORD(myPoints);
  384.         myMsg.pt.y = HIWORD(myPoints);
  385.  
  386.         // translate a Windows event to a Mac event
  387.         WinEventToMacEvent(&myMsg, &myMacEvent);
  388.  
  389.         // let the application-specific code have a chance to intercept the event
  390.         myIsHandled = QTApp_HandleEvent(&myMacEvent);
  391.         
  392.         // pass the Mac event to the movie controller, but only if the movie window isn't minimized
  393.         if (!myIsHandled)
  394.             if (myMC != NULL)
  395.                 if (!IsIconic(theWnd))
  396.                     myIsHandled = MCIsPlayerEvent(myMC, (EventRecord *)&myMacEvent);
  397.     }
  398.  
  399.     switch (theMessage) {
  400.         case WM_CREATE:
  401.             // create a new window object associated with the new window
  402.             QTFrame_CreateWindowObject(theWnd);
  403.             break;
  404.  
  405.         case WM_WINDOWPOSCHANGING:
  406.             // don't show the window until we have created a movie and
  407.             // can therefore properly size the window to contain the movie
  408.             if (gWeAreCreatingWindow) {
  409.                 WINDOWPOS    *lpWindowPos = (WINDOWPOS*)lParam;
  410.                 
  411.                 lpWindowPos->flags &= ~SWP_SHOWWINDOW;
  412.             }
  413.             break;
  414.  
  415.         case WM_WINDOWPOSCHANGED:
  416.             // if a movie window has become minimized, stop the movie
  417.             if (IsIconic(theWnd))
  418.                 StopMovie(myMovie);
  419.             break;
  420.  
  421.         case WM_SIZE:
  422.             // resize the movie and controller to fit the window
  423.             myWidth = LOWORD(lParam);
  424.             myHeight = HIWORD(lParam);
  425.             
  426.             // we do NOT want to resize the movie controller if the window is minimized,
  427.             // if there is no movie controller, or if we are in the middle of resizing the window
  428.             if (!gWeAreSizingWindow && (myMC != NULL) && !IsIconic(theWnd)) {
  429.                 Rect        myRect;
  430.                 
  431.                 myRect.top = 0;
  432.                 myRect.left = 0;
  433.                 myRect.right = myWidth;
  434.                 myRect.bottom = myHeight;
  435.                 
  436.                 MCSetControllerBoundsRect(myMC, &myRect);
  437.             }
  438.             break;
  439.  
  440.         case WM_MOUSEMOVE:
  441.             // for QuickTime movies (but NOT for QuickTime VR movies), set the cursor to the arrow cursor
  442.             if (myWindowObject != NULL)
  443.                 if (!(**myWindowObject).fIsQTVRMovie)
  444.                     SetCursor(LoadCursor(NULL, IDC_ARROW));
  445.             break;
  446.  
  447.         case WM_PUMPMOVIE:
  448.             // we receive this message only to task the movie
  449.             break;
  450.  
  451.         case WM_LBUTTONDOWN:
  452.             // do any application-specific mouse-button handling, but only if the message hasn't already been handled
  453.             if (!myIsHandled)
  454.                 QTApp_HandleContentClick(theWnd, &myMacEvent);
  455.             break;
  456.  
  457.         case WM_CHAR:
  458.             // do any application-specific key press handling
  459.             QTApp_HandleKeyPress((char)wParam);
  460.             break;
  461.  
  462.         case WM_PAINT: {
  463.             // do any application-specific drawing in the window
  464.                 PAINTSTRUCT        myPaintStruct;
  465.             
  466.                 BeginPaint(theWnd, &myPaintStruct);
  467.  
  468.                 // if the window contains an image, draw it using GraphicsImportDraw
  469.                 if (myWindowObject != NULL)
  470.                     if ((**myWindowObject).fGraphicsImporter != NULL)
  471.                         GraphicsImportDraw((**myWindowObject).fGraphicsImporter);
  472.             
  473.                 QTApp_Draw(theWnd, NULL);
  474.                 EndPaint(theWnd, &myPaintStruct);
  475.             }
  476.             break;
  477.  
  478.         case WM_MDIACTIVATE:
  479.             // activate or deactivate the movie controller in the specified window
  480.             QTFrame_ActivateController(theWnd, (HWND)theWnd == (HWND)lParam);
  481.             break;
  482.  
  483.         case WM_COMMAND: {
  484.  
  485.             switch (LOWORD(wParam)) {
  486.                             
  487.                 case IDM_FILESAVE:
  488.                 case IDM_FILESAVEAS:
  489.                     QTFrame_HandleFileMenuItem(theWnd, LOWORD(wParam));
  490.                     break;
  491.  
  492.                 case IDM_EDITUNDO:
  493.                 case IDM_EDITCUT:
  494.                 case IDM_EDITCOPY:
  495.                 case IDM_EDITPASTE:
  496.                 case IDM_EDITCLEAR:
  497.                 case IDM_EDITSELECTALL:
  498.                 case IDM_EDITSELECTNONE:
  499.                     QTFrame_HandleEditMenuItem(theWnd, LOWORD(wParam));
  500.                     break;
  501.                     
  502.                 default:
  503.                     // do any application-specific menu handling
  504.                     QTApp_HandleMenu((UInt16)LOWORD(wParam));
  505.                     break;
  506.             }
  507.             
  508.             break;
  509.         }    // case WM_COMMAND
  510.  
  511.         case WM_GETMINMAXINFO:
  512.             QTFrame_CalcWindowMinMaxInfo(theWnd, (LPMINMAXINFO)lParam);
  513.             break;
  514.  
  515.         case WM_CLOSE:
  516.             // prepare to close the window, making sure that any changed data is saved or explicitly discarded;
  517.             // we can still cancel the window closing here
  518.             if (myWindowObject != NULL) {
  519.             
  520.                 // if the window's data is "dirty", give the user a chance to save it
  521.                 if ((**myWindowObject).fIsDirty) {
  522.                     int            myItem;
  523.                     char        myText[256];
  524.                     UINT        myAction;
  525.         
  526.                     // get the title of the window
  527.                     GetWindowText(theWnd, myText, sizeof(myText));
  528.         
  529.                     // specify the action
  530.                     myAction = gShuttingDown ? IDS_SAVEONQUIT : IDS_SAVEONCLOSE;
  531.         
  532.                     // display the "Save changes" dialog box
  533.                     myItem = QTFrame_ShowCautionAlert(theWnd, myAction, MB_ICONEXCLAMATION, MB_YESNOCANCEL, gAppName, myText);
  534.                     switch (myItem) {
  535.                         case kSaveChanges:
  536.                             // save the data in the window
  537.                             QTFrame_UpdateMovieFile(theWnd);
  538.                             break;
  539.                             
  540.                         case kCancelClose:
  541.                             // do not close the window and do not quit the application
  542.                             gShuttingDown = false;
  543.                             return(0);
  544.                         
  545.                         case kDontSaveChanges:
  546.                             // discard any unsaved changes (that is, don't do anything)
  547.                             break;
  548.                             
  549.                         default:
  550.                             // unexpected item selected; just return
  551.                             return(0);
  552.                     }
  553.                 }
  554.             } // if (myWindowObject != NULL)
  555.             
  556.             // if we got to this point, it's okay to close and destroy the window
  557.             SendMessage(ghWndMDIClient, WM_MDIDESTROY, (WPARAM)theWnd, 0L);
  558.             break;
  559.  
  560.         case WM_DESTROY:
  561.             // when we get this message,
  562.             // the window has been removed from the screen and its associated data must be destroyed
  563.             if (myWindowObject != NULL)
  564.                 QTFrame_CloseWindowObject(myWindowObject);
  565.         
  566.             SetWindowLong(theWnd, GWL_USERDATA, 0);
  567.  
  568.             // destroy the port association
  569.             DestroyPortAssociation((CGrafPtr)GetHWNDPort(theWnd));
  570.             
  571.             break;
  572.     }
  573.  
  574.     return(DefMDIChildProc(theWnd, theMessage, wParam, lParam));
  575. }
  576.  
  577.  
  578. //////////
  579. //
  580. // QTFrame_QuitFramework
  581. // Do any framework-specific shut-down.
  582. //
  583. //////////
  584.  
  585. void QTFrame_QuitFramework (void)
  586. {
  587.     // set our global flag to indicate we're shutting down
  588.     gShuttingDown = true;
  589.     
  590.     // do application-specific processing that must occur before movie windows are closed
  591.     QTApp_Stop(kStopAppPhase_BeforeDestroyWindows);
  592.     
  593.     // close all open movie windows; note that the user can cancel the shutting down
  594.     QTFrame_CloseMovieWindows();
  595.     
  596.     // close the frame window, if we're still shutting down
  597.     if (gShuttingDown)
  598.         SendMessage(ghWnd, WM_CLOSE, 0, 0L);
  599. }
  600.  
  601.  
  602. //////////
  603. //
  604. // QTFrame_OpenCommandLineMovies
  605. // Parse the command line when the application first starts up and
  606. // open as movie documents any files specified on the command line.
  607. //
  608. // Based on the routine ParseCmdLinePriv in GraphicImporter.c.
  609. //
  610. //////////
  611.  
  612. void QTFrame_OpenCommandLineMovies (LPSTR theCmdLine)
  613. {
  614. #pragma unused(theCmdLine)
  615.     LPSTR                myCmdLine;
  616.     FSSpec                myFSSpec;
  617.     SHFILEINFO            myFileInfo;
  618.     
  619.     // get the command line for the current process
  620.     myCmdLine = GetCommandLine();
  621.  
  622.     // parse the command line
  623.     if (*myCmdLine) {
  624.         LPSTR            myTempLine;
  625.         
  626.         // the string preceding any white space is the name of the module (that is, the application)
  627.         myTempLine = strchr(myCmdLine, ' ');
  628.         if (myTempLine) {
  629.             myCmdLine = myTempLine;                  // skip the name of the application
  630.             while (*myCmdLine == ' ')
  631.                 myCmdLine++;                        // skip spaces to end of string or to first command
  632.  
  633.             while (*myCmdLine != '\0') {
  634.                 char     myFileName[MAX_PATH];
  635.                 char     myTempName[MAX_PATH];
  636.                 char     myBuffName[MAX_PATH];
  637.                 int     myIndex;
  638.                 
  639.                 // read thru the remaining string to find file names
  640.                 for (myIndex = 0; *myCmdLine != '\0'; myIndex++, myCmdLine++) {
  641.                     // if we encounter a space character, it might be a filename delimiter or a space in the filename;
  642.                     // we'll try to open the filename we have so far to see whether it's a valid filename; if not, the
  643.                     // space must be part of the filename we're constructing
  644.                     if (*myCmdLine == ' ') {
  645.                         HANDLE                myFindFile;
  646.                         WIN32_FIND_DATA        myFile;
  647.                     
  648.                         myTempName[myIndex] = '\0';
  649.                         strcpy(myBuffName, myTempName);
  650.                         
  651.                         myFindFile = FindFirstFile(myBuffName, &myFile);
  652.                         if (myFindFile != INVALID_HANDLE_VALUE) {
  653.                             // we found a file having the specified name; close our file search and
  654.                             // break out of our character-gobbling loop (since we've got a valid filename)
  655.                             FindClose(myFindFile);
  656.                             break;
  657.                         }
  658.                     }
  659.                 
  660.                     // if we made it here, *myCmdLine is part of the filename (possibly a space)
  661.                     myFileName[myIndex] = myTempName[myIndex] = *myCmdLine;
  662.                 }
  663.                 
  664.                 if (*myCmdLine != '\0')
  665.                     myCmdLine++;
  666.                 
  667.                 // add a terminating NULL character
  668.                 myFileName[myIndex] = '\0';
  669.  
  670.                 // make sure the filename picks out a QuickTime movie
  671.                 SHGetFileInfo(myFileName, (DWORD)0, &myFileInfo, sizeof(myFileInfo), SHGFI_TYPENAME);
  672.                 if (strcmp(myFileInfo.szTypeName, gMovieType) != 0)
  673.                     continue;
  674.                 
  675.                 // make an FSSpec record
  676.                 NativePathNameToFSSpec(myFileName, &myFSSpec, 0L);
  677.  
  678.                 // open the file in a movie window
  679.                 QTFrame_OpenMovieInWindow(NULL, &myFSSpec);
  680.             }
  681.  
  682.         } else
  683.             myCmdLine += strlen(myCmdLine);           // point to NULL
  684.     }
  685. }
  686.  
  687.  
  688. //////////
  689. //
  690. // QTFrame_CreateMovieWindow
  691. // Create a new window to display the movie in.
  692. //
  693. //////////
  694.  
  695. WindowReference QTFrame_CreateMovieWindow (void)
  696. {
  697.     WindowReference            myWindow = NULL;
  698.     WindowObject            myWindowObject = NULL;
  699.  
  700.     gWeAreCreatingWindow = true;
  701.     
  702.     // create a new window to display the movie in
  703.     myWindow = CreateWindowEx(WS_EX_MDICHILD,
  704.                                gChildName,
  705.                                "",
  706.                                0,
  707.                                CW_USEDEFAULT,
  708.                                CW_USEDEFAULT,
  709.                                CW_USEDEFAULT,
  710.                                CW_USEDEFAULT,
  711.                                ghWndMDIClient, 
  712.                                NULL,
  713.                                ghInst,
  714.                                0);
  715.     
  716.     // CreateWindowEx sends a WM_CREATE message to the window being created;
  717.     // we'll call QTFrame_CreateWindowObject when processing that message
  718.     
  719.     gWeAreCreatingWindow = false;
  720.  
  721.     return(myWindow);
  722. }
  723.  
  724.  
  725. //////////
  726. //
  727. // QTFrame_DestroyMovieWindow
  728. // Close the specified movie window.
  729. //
  730. //////////
  731.  
  732. void QTFrame_DestroyMovieWindow (WindowReference theWindow)
  733. {
  734. #pragma unused(theWindow)
  735.  
  736.     HWND                myChild = NULL;
  737.     
  738.     // close the active child window
  739.     myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  740.     if (IsWindow(myChild))
  741.         SendMessage(myChild, WM_CLOSE, 0L, 0L);
  742. }
  743.  
  744.  
  745. //////////
  746. //
  747. // QTFrame_GetDisplayName
  748. // Given a full pathname, return the part that trails the rightmost path separator,
  749. // in long file name format (not in 8.3 format).
  750. //
  751. //////////
  752.  
  753. void QTFrame_GetDisplayName (char *thePathName, char *theDispName)
  754. {
  755.     SHFILEINFO            myFileInfo;
  756.     DWORD                myResult;
  757.     
  758.     myResult = SHGetFileInfo(thePathName, (DWORD)0, &myFileInfo, sizeof(myFileInfo), SHGFI_DISPLAYNAME);
  759.     if (myResult != 0) {
  760.         // SHGetFileInfo successful
  761.         strcpy(theDispName, myFileInfo.szDisplayName);
  762.     } else {
  763.         // SHGetFileInfo not successful, so find the basename ourselves
  764.         short    myLength = 0;
  765.         short    myIndex;
  766.  
  767.         // get the length of the pathname
  768.         myLength = strlen(thePathName);
  769.         
  770.         // find the position of the rightmost path separator in thePathName
  771.         if (strchr(thePathName, kWinFilePathSeparator) != NULL) {
  772.     
  773.             myIndex = myLength - 1;
  774.             while (thePathName[myIndex] != kWinFilePathSeparator)
  775.                 myIndex--;
  776.                 
  777.             // calculate the length of the basename
  778.             myLength = myLength - myIndex - 1;
  779.     
  780.         } else {
  781.             // there is no rightmost path separator in thePathName;
  782.             // set myIndex so that myIndex + 1 == 0, for the call to BlockMove below
  783.             myIndex = -1;
  784.         }
  785.         
  786.         // copy into theDispName the substring of thePathName from myIndex + 1 to the end
  787.         BlockMove(&thePathName[myIndex + 1], theDispName, myLength);
  788.         theDispName[myLength] = '\0';
  789.     }
  790. }
  791.  
  792.  
  793. //////////
  794. //
  795. // QTFrame_ShowAboutBox 
  796. // Display and manage the About dialog box.
  797. //
  798. //////////
  799.  
  800. void QTFrame_ShowAboutBox (void)
  801. {
  802.     DialogBox(ghInst, MAKEINTRESOURCE(IDD_ABOUT), ghWnd, (DLGPROC)QTFrame_DialogProcedure);
  803. }
  804.  
  805.  
  806. //////////
  807. //
  808. // QTFrame_ShowCautionAlert 
  809. // Display and manage a caution alert.
  810. //
  811. // Based on ShowUserMessage by Stephen Chernicoff, in his WiniEdit application
  812. // (as described in the book "From Mac to Windows" on CodeWarrior reference CD).
  813. //
  814. //////////
  815.  
  816. int QTFrame_ShowCautionAlert (HWND theWnd, UINT theID, UINT theIconStyle, UINT theButtonStyle, LPSTR theTitle, LPSTR theArgument)
  817. {
  818.     char            myTemplate[kAlertMessageMaxLength];
  819.     char            myText[kAlertMessageMaxLength];
  820.     UINT            myStyle;
  821.     int                myItem;
  822.     
  823.     // beep, to get the user's attention (just like CautionAlert on MacOS)
  824.     QTFrame_Beep();
  825.     
  826.     // load the message text template from a resource
  827.     LoadString(ghInst, theID, myTemplate, sizeof(myTemplate));
  828.     
  829.     // insert argument into the message text template, to get the message text
  830.     wsprintf(myText, myTemplate, theArgument);
  831.     
  832.     // set the dialog box style
  833.     myStyle = theIconStyle | theButtonStyle | MB_APPLMODAL | MB_SETFOREGROUND;
  834.  
  835.     // display the dialog box
  836.     myItem = MessageBox(theWnd, myText, theTitle, myStyle);
  837.     
  838.     return(myItem);
  839. }
  840.  
  841.  
  842. //////////
  843. //
  844. // QTFrame_DialogProcedure 
  845. // Dialog callback procedure.
  846. //
  847. //////////
  848.  
  849. static UINT APIENTRY QTFrame_DialogProcedure (HWND theDialog, UINT theMessage, WPARAM wParam, LPARAM lParam)
  850. {
  851.     BOOL    isHandled = false;
  852.  
  853.     switch (theMessage) {
  854.     
  855.         case WM_INITDIALOG: {
  856.             Point            myPoint;
  857.             long            myWidth;
  858.             long            myHeight;
  859.             RECT            myRect;
  860.             RECT            myDeskRect;
  861.             HWND            myWindow;
  862.             OPENFILENAME    *myOFNPtr = (OPENFILENAME *)lParam;
  863.             
  864.             myWindow = theDialog;
  865.                 
  866.             // check whether theDialog is the Open File common dialog box
  867.             
  868.             // we need to do this because, for the Open File dialog box, theDialog isn't
  869.             // the actual visible dialog box, but an invisible child of the visible dialog box;
  870.             // for WM_INITDIALOG, lParam is the address of the structure passed to GetOpenFileName,
  871.             // so we can just look for the value we previously put into the lCustData field
  872.             // to make sure that we've got the correct dialog.
  873.             if (myOFNPtr != NULL)
  874.                 if (myOFNPtr->lCustData == kOpenDialogCustomData)
  875.                     myWindow = GetParent(theDialog);
  876.                 
  877.             // center the dialog window on the screen
  878.             GetWindowRect(myWindow, &myRect);
  879.             myWidth = myRect.right - myRect.left;
  880.             myHeight = myRect.bottom - myRect.top;
  881.             GetWindowRect(GetDesktopWindow(), &myDeskRect);
  882.             myPoint.h = (short)((myDeskRect.right + myDeskRect.left)/2 - myWidth/2);
  883.             myPoint.v = (short)((myDeskRect.top + myDeskRect.bottom)/3 - myHeight/3);
  884.             SetWindowPos(myWindow, 0, myPoint.h, myPoint.v, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
  885.             
  886.             // let Windows set the input focus
  887.             isHandled = true;
  888.             break;
  889.         }
  890.         
  891.         case WM_CLOSE:
  892.             EndDialog(theDialog, IDOK);
  893.             isHandled = true;
  894.             break;
  895.         
  896.         case WM_COMMAND:
  897.             switch (LOWORD(wParam)) {
  898.                 case IDOK:
  899.                     EndDialog(theDialog, IDOK);
  900.                     isHandled = true;
  901.                     break;
  902.                 default:
  903.                     isHandled = false;
  904.                     break;
  905.             }
  906.             break;
  907.         
  908.         default:
  909.             isHandled = false;
  910.             break;
  911.     }
  912.  
  913.     return(isHandled);
  914. }
  915.  
  916.  
  917. //////////
  918. //
  919. // QTFrame_CalcWindowMinMaxInfo 
  920. // Get minimum and maximum possible size of this window.
  921. //
  922. //////////
  923.  
  924. static void QTFrame_CalcWindowMinMaxInfo (HWND theWnd, LPMINMAXINFO lpMinMax)
  925. {
  926.     WindowObject        myWindowObject = NULL;
  927.     MovieController        myMC = NULL;
  928.     Movie                myMovie = NULL;
  929.  
  930.     myWindowObject = QTFrame_GetWindowObjectFromWindow(theWnd);
  931.     if (myWindowObject != NULL) {
  932.         myMC = (**myWindowObject).fController;
  933.         myMovie = (**myWindowObject).fMovie;
  934.     }
  935.  
  936.     if (myMC && myMovie) {
  937.         Rect            myMovieBox;
  938.         short            myControllerHeight = 0;                    // assume there's no controller bar
  939.         
  940.         if (MCGetVisible(myMC))
  941.             myControllerHeight = QTUtils_GetControllerBarHeight(myMC);
  942.  
  943.         lpMinMax->ptMinTrackSize.x = gMCResizeBounds.left + (2 * GetSystemMetrics(SM_CXFRAME));
  944.         
  945.         GetMovieBox(myMovie, &myMovieBox);
  946.         if (myMovieBox.bottom - myMovieBox.top != 0)
  947.             lpMinMax->ptMinTrackSize.y = 
  948.                 gMCResizeBounds.top +                            // growbounds height +
  949.                 (2 * GetSystemMetrics(SM_CXFRAME)) +            // frame thickness +
  950.                 GetSystemMetrics(SM_CYCAPTION) +                // caption height +
  951.                 -1 +                                            // fudge factor +
  952.                 myControllerHeight;                                // movie controller bar height
  953.         else
  954.             lpMinMax->ptMaxSize.y =
  955.             lpMinMax->ptMaxTrackSize.y =
  956.             lpMinMax->ptMinTrackSize.y = 
  957.                 0 +                                                // height of audio only movie +
  958.                 (2 * GetSystemMetrics(SM_CXFRAME)) +            // frame thickness +
  959.                 GetSystemMetrics(SM_CYCAPTION) +                // caption height +
  960.                 -1 +                                            // fudge factor +
  961.                 myControllerHeight;                                // movie controller bar height
  962.     }
  963. }
  964.  
  965.  
  966.